/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.isfd.constant.enums.IsfdBusinessDatabaseTypeEnum;
import com.comac.ins.isfd.constant.enums.IsfdMongoQueryOperatorEnum;
import com.comac.ins.isfd.domain.IsfdBusinessDatabaseRef;
import com.comac.ins.isfd.domain.IsfdDatabaseMongoQuery;
import com.comac.ins.isfd.domain.IsfdDatabaseTypeManagement;
import com.comac.ins.isfd.domain.bo.IsfdBusinessDatabaseRefBo;
import com.comac.ins.isfd.domain.bo.IsfdDatabaseDataImportRecordBo;
import com.comac.ins.isfd.domain.vo.*;
import com.comac.ins.isfd.mapper.IsfdBusinessDatabaseRefMapper;
import com.comac.ins.isfd.mapper.IsfdDatabaseTypeManagementMapper;
import com.comac.ins.isfd.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;


@RequiredArgsConstructor
@Service
public class IsfdBusinessDatabaseRefServiceImpl implements IIsfdBusinessDatabaseRefService {

    @Autowired
    private IsfdBusinessDatabaseRefMapper baseMapper;
    @Autowired
    private IIsfdDatabaseDataImportRecordService iIsfdDatabaseDataImportRecordService;
    @Autowired
    private IIsfdDatabaseMongoService iIsfdDatabaseMongoService;
    @Autowired
    private IIsfdDatabaseModelConfigService modelConfigService;
    @Autowired
    private IIsfdSceneMapService iIsfdSceneMapService;
    @Autowired
    private IsfdDatabaseTypeManagementMapper isfdDatabaseTypeManagementMapper;

    @Override
    public List<IsfdBusinessDatabaseRefVo> selectDataBaseRefByCondition(List<Long> sceneIds,
                                                                        List<Long> dataBaseTypeIds,
                                                                        List<Long> systemsIds,
                                                                        List<Long> modelIds) {
        return baseMapper.selectDataBaseRefByCondition(sceneIds, systemsIds, modelIds, dataBaseTypeIds);
    }


    private String generateParentKey(Integer level, String nodeKey) {
        if (level == 1) {
            return null; // 场景节点无父节点
        }
        return StringUtils.substringBeforeLast(nodeKey, "_");
    }

    @Override
    public Boolean save(IsfdBusinessDatabaseRefBo bo) {
        IsfdBusinessDatabaseRef one = baseMapper.selectOne(new LambdaQueryWrapper<IsfdBusinessDatabaseRef>()
            .eq(IsfdBusinessDatabaseRef::getSceneId, bo.getSceneId())
            .eq(IsfdBusinessDatabaseRef::getDatabaseTypeId, bo.getDatabaseTypeId())
            .eq(IsfdBusinessDatabaseRef::getSystemId, bo.getSystemId())
            .eq(IsfdBusinessDatabaseRef::getParentModelId, bo.getParentModelId()));
        if (one != null) {
            bo.setId(one.getId());
            return Boolean.TRUE;
        }
        IsfdBusinessDatabaseRef po = MapstructUtils.convert(bo, IsfdBusinessDatabaseRef.class);
        baseMapper.insert(po);
        bo.setId(po.getId());
        return Boolean.TRUE;
    }

    @Override
    public void updateHaveImportData(IsfdBusinessDatabaseRefBo bo) {
        LambdaQueryWrapper<IsfdBusinessDatabaseRef> lambdaQueryWrapper = new LambdaQueryWrapper<IsfdBusinessDatabaseRef>()
            .eq(IsfdBusinessDatabaseRef::getSceneId, bo.getSceneId())
            .eq(IsfdBusinessDatabaseRef::getDatabaseTypeId, bo.getDatabaseTypeId())
            .eq(IsfdBusinessDatabaseRef::getParentModelId, bo.getParentModelId());
        if (bo.getSystemId() != null) {
            lambdaQueryWrapper.eq(IsfdBusinessDatabaseRef::getSystemId, bo.getSystemId());
        }
        IsfdBusinessDatabaseRef one = baseMapper.selectOne(lambdaQueryWrapper);
        if (one == null) {
            return;
        }
        one.setHaveImportData(1);
        baseMapper.updateById(one);
    }


    /**
     * 根据dataList 构造树
     */
    private List<IsfdBusinessDatabaseRefTreeVo> buildTree(List<IsfdBusinessDatabaseRefWithNameVo> dataList, Boolean needModelChild) {
        // 3. 构建树形结构（重点修改部分）
        Map<String, IsfdBusinessDatabaseRefTreeVo> nodeMap = new HashMap<>();
        List<IsfdBusinessDatabaseRefTreeVo> rootNodes = new ArrayList<>();

        for (IsfdBusinessDatabaseRefWithNameVo data : dataList) {
            // 3.1 先处理数据库类型层级（新的根节点）
            Long databaseTypeId = data.getDatabaseTypeId();
            Integer databaseLevel = data.getDataBaseLevel() != null ? data.getDataBaseLevel() : 1;
            Long topDatabaseId = null;
            Long currentDatabaseId = null;

            if (databaseTypeId != null) {
                IsfdDatabaseTypeManagementVo databaseType = isfdDatabaseTypeManagementMapper.selectVoById(databaseTypeId);
                if (databaseType != null) {
                    topDatabaseId = databaseType.getTopId();
                    currentDatabaseId = databaseLevel == 1 ? topDatabaseId : databaseTypeId;

                    // 创建一级数据库节点（新的根节点，level=1）
                    if (topDatabaseId != null) {
                        IsfdDatabaseTypeManagementVo topDatabase = isfdDatabaseTypeManagementMapper.selectVoById(topDatabaseId);
                        createNodeIfAbsentV3(
                            topDatabaseId,
                            topDatabase.getDatabaseName(),
                            1, // 修改层级为1
                            IsfdBusinessDatabaseTypeEnum.DATABASE_1.getValue(),
                            null,
                            needModelChild,
                            nodeMap,
                            rootNodes,
                            String.valueOf(topDatabaseId),
                            null
                        );
                    }

                    // 创建二级数据库节点（level=2）
                    if (databaseLevel == 2) {
                        createNodeIfAbsentV3(
                            databaseTypeId,
                            data.getDataBaseName(),
                            2,
                            IsfdBusinessDatabaseTypeEnum.DATABASE_2.getValue(),
                            null,
                            needModelChild,
                            nodeMap,
                            rootNodes,
                            topDatabaseId + "_" + databaseTypeId,
                            null
                        );
                    }
                }
            }

            // 3.2 场景节点（下移到数据库类型下，level=3）
            Long sceneId = data.getSceneId();
            String parentKeyForScene = databaseLevel == 1 ?
                String.valueOf(topDatabaseId) :
                topDatabaseId + "_" + currentDatabaseId;

            Integer sceneLevel = databaseLevel == 1 ? 2 : 3;
            createNodeIfAbsentV3(
                sceneId,
                data.getSceneName(),
                sceneLevel,
                IsfdBusinessDatabaseTypeEnum.SCENE.getValue(),
                null,
                needModelChild,
                nodeMap,
                rootNodes,
                parentKeyForScene + "_" + sceneId,
                null
            );

            // 3.3 业务系统节点（level=4）
            String modelType = data.getModelType();
            boolean isGeneralModel = IsfdBusinessDatabaseTypeEnum.COMMON_MODEL.getValue().equals(modelType);
            Long systemId = data.getSystemId();

            Integer systemLevel = null;
            if (!isGeneralModel && systemId != null) {
                systemLevel = sceneLevel == 2 ? 3 : 4;
                createNodeIfAbsentV3(
                    systemId,
                    data.getSystemName(),
                    systemLevel,
                    IsfdBusinessDatabaseTypeEnum.SYSTEM.getValue(),
                    null,
                    needModelChild,
                    nodeMap,
                    rootNodes,
                    parentKeyForScene + "_" + sceneId + "_" + systemId,
                    null
                );
            }

            // 3.4 模型节点处理（level=5）
            Long modelId = data.getParentModelId();
            if (modelId != null) {
                // 设置modelLevel
                Integer modelLevel = null;
                if (systemLevel == null) {
                    modelLevel = sceneLevel == 2 ? 3 : 4;
                } else {
                    modelLevel = systemLevel == 3 ? 4 : 5;
                }

                String parentKey = isGeneralModel ?
                    parentKeyForScene + "_" + sceneId : // 通用模型挂在场景下
                    parentKeyForScene + "_" + sceneId + "_" + systemId; // 普通模型挂在系统下

                createNodeIfAbsentV3(
                    modelId,
                    data.getModelName(),
                    modelLevel, // 最终层级
                    isGeneralModel ?
                        IsfdBusinessDatabaseTypeEnum.COMMON_MODEL.getValue() :
                        IsfdBusinessDatabaseTypeEnum.MODEL.getValue(),
                    data.getVersionNumber(),
                    needModelChild,
                    nodeMap,
                    rootNodes,
                    parentKey + "_" + modelId,
                    data.getDatabaseTypeId()
                );
            }
        }

        // 4. 构建父子关系
        for (IsfdBusinessDatabaseRefTreeVo node : nodeMap.values()) {
            String parentKey = node.getParentKey();
            if (parentKey != null && nodeMap.containsKey(parentKey)) {
                if (nodeMap.get(parentKey).getChildren() == null) {
                    nodeMap.get(parentKey).setChildren(new ArrayList<>());
                }
                nodeMap.get(parentKey).getChildren().add(node);
            }
        }
        return rootNodes;
    }

    @Override
    public List<IsfdBusinessDatabaseRefTreeVo> baseTreeV3(String dataBaseName, String matchName) {
        // 1. 数据准备
        List<Long> dataBaseTypeIds = new ArrayList<>();
        IsfdDatabaseTypeManagementVo targetVo = isfdDatabaseTypeManagementMapper.selectVoOne(
            new LambdaQueryWrapper<IsfdDatabaseTypeManagement>()
                .eq(IsfdDatabaseTypeManagement::getDatabaseName, dataBaseName));
        if (targetVo != null) {
            Long topId = targetVo.getTopId();
            List<IsfdDatabaseTypeManagementVo> databaseTypes = isfdDatabaseTypeManagementMapper.selectVoList(
                new LambdaQueryWrapper<IsfdDatabaseTypeManagement>()
                    .in(IsfdDatabaseTypeManagement::getTopId, topId));
            dataBaseTypeIds = databaseTypes.stream()
                .map(IsfdDatabaseTypeManagementVo::getId).toList();
        }

        if (CollectionUtils.isEmpty(dataBaseTypeIds)) {
            return new ArrayList<>();
        }

        // 2. 获取基础数据
        List<IsfdBusinessDatabaseRefWithNameVo> dataList = baseMapper.getAllVersionDataWithNames(
            null,
            null,
            null,
            dataBaseTypeIds
        );

        if (CollectionUtils.isEmpty(dataList)) {
            return new ArrayList<>();
        }

        // 3.如果存在节点筛选，那么进行筛选
        if (StringUtils.isNotBlank(matchName)) {
            dataList = dataList.stream().filter(d -> {
                String targetDataBaseName = d.getDataBaseName();
                String sceneName = d.getSceneName();
                String systemName = d.getSystemName();
                String modelName = d.getModelName();
                if (targetDataBaseName.contains(matchName)
                    || sceneName.contains(matchName)
                    || StringUtils.isNotBlank(systemName) && systemName.contains(matchName)
                    || modelName.contains(matchName)) {
                    return Boolean.TRUE;
                } else {
                    return Boolean.FALSE;
                }
            }).toList();
        }

        // 4.构造树
        return buildTree(dataList, Boolean.FALSE);
    }


    @Override
    public List<IsfdBusinessDatabaseRefTreeVo> mapTreeV3(Long sceneId, Long systemId) {
        // 1. 获取基础数据
        List<IsfdBusinessDatabaseRefWithNameVo> dataList = baseMapper.getLastVersionDataWithNames(
            Collections.singletonList(sceneId),
            null,
            null,
            null
        );
        // 要找到系统以下的子节点和兄弟节点的通用节点
        if (!CollectionUtils.isEmpty(dataList)) {
            dataList = dataList.stream().filter(d -> IsfdBusinessDatabaseTypeEnum.COMMON_MODEL.getValue().equals(d.getModelType())
                || systemId.equals(d.getSystemId())).toList();
        }


        if (CollectionUtils.isEmpty(dataList)) {
            return new ArrayList<>();
        }

        return buildTree(dataList, Boolean.FALSE);
    }

    private void createNodeIfAbsentV3(Long nodeId,
                                      String name,
                                      Integer level,
                                      String type,
                                      String versionNumber,
                                      Boolean needModelChild,
                                      Map<String, IsfdBusinessDatabaseRefTreeVo> nodeMap,
                                      List<IsfdBusinessDatabaseRefTreeVo> rootNodes,
                                      String nodeKey,
                                      Long databaseTypeId) {
        if (!nodeMap.containsKey(nodeKey)) {
            IsfdBusinessDatabaseRefTreeVo node = new IsfdBusinessDatabaseRefTreeVo();
            node.setId(nodeId);
            node.setName(name);
            node.setLevel(level);
            node.setLevelId(nodeId);
            node.setNodeKey(nodeKey);
            node.setParentKey(generateParentKey(level, nodeKey));
            node.setType(type);


            if (level == 1) {
                rootNodes.add(node);
            }

            if (versionNumber != null) {
                node.setVersionNumber(versionNumber);
            }

            if (databaseTypeId != null) {
                node.setDatabaseTypeId(databaseTypeId);
            }

            nodeMap.put(nodeKey, node);

            // 处理模型子节点
            if (needModelChild && (IsfdBusinessDatabaseTypeEnum.MODEL.getValue().equals(type) ||
                IsfdBusinessDatabaseTypeEnum.COMMON_MODEL.getValue().equals(type))) {
                List<IsfdDatabaseModelConfigVo> allModelChildren = modelConfigService.getAllChildrenByParentConfigId(nodeId);
                if (!CollectionUtils.isEmpty(allModelChildren)) {
                    for (IsfdDatabaseModelConfigVo modelConfigVo : allModelChildren) {
                        IsfdBusinessDatabaseRefTreeVo childNode = new IsfdBusinessDatabaseRefTreeVo();
                        childNode.setId(modelConfigVo.getId());
                        childNode.setLevelId(modelConfigVo.getId());
                        childNode.setName(modelConfigVo.getModelName());
                        childNode.setVersionNumber(modelConfigVo.getVersionNumber());
                        childNode.setType(type);
                        childNode.setLevel(level + 1);
                        String childNodeKey = nodeKey + "_" + modelConfigVo.getId();
                        childNode.setNodeKey(childNodeKey);
                        childNode.setParentKey(nodeKey);
                        childNode.setDatabaseTypeId(databaseTypeId);
                        nodeMap.put(childNodeKey, childNode);
                    }
                }
            }
        }
    }

    @Override
    public IsfdBusinessDatabaseRefVo queryByKey(Long sceneId, Long databaseTypeId, Long systemId, Long parentModelId) {
        return baseMapper.selectVoOne(new LambdaQueryWrapper<IsfdBusinessDatabaseRef>()
            .eq(IsfdBusinessDatabaseRef::getSceneId, sceneId)
            .eq(IsfdBusinessDatabaseRef::getDatabaseTypeId, databaseTypeId)
            .eq(IsfdBusinessDatabaseRef::getSystemId, systemId)
            .eq(IsfdBusinessDatabaseRef::getParentModelId, parentModelId));
    }

    @Override
    public void preDelete(List<Long> sceneIds, List<Long> dataBaseTypeIds, List<Long> systemsIds, List<Long> modelIds) {
        List<IsfdBusinessDatabaseRefWithNameVo> refVoList = baseMapper.getAllDataWithNames(sceneIds, dataBaseTypeIds, systemsIds, modelIds);
        if (!CollectionUtils.isEmpty(refVoList)) {
            for (IsfdBusinessDatabaseRefWithNameVo refVo : refVoList) {
                Long parentModelId = refVo.getParentModelId();
                IsfdDatabaseDataImportRecordBo recordBo = new IsfdDatabaseDataImportRecordBo();
                recordBo.setModelId(parentModelId);
                List<IsfdDatabaseDataImportRecordVo> recordVoList = iIsfdDatabaseDataImportRecordService.queryList(recordBo);
                for (IsfdDatabaseDataImportRecordVo recordVo : recordVoList) {
                    String tableName = recordVo.getTableName();
                    Long recordId = recordVo.getId();
                    IsfdDatabaseMongoQuery isfdDatabaseMongoQuery = new IsfdDatabaseMongoQuery();
                    List<IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition> conditions = new ArrayList<>();
                    IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition recordCondition = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
                    recordCondition.setFieldName("importRecord.id");
                    recordCondition.setOperator(IsfdMongoQueryOperatorEnum.EQUAL.getValue());
                    recordCondition.setValue(String.valueOf(recordId));
                    recordCondition.setValueNumberCheck(Boolean.TRUE);
                    conditions.add(recordCondition);
                    isfdDatabaseMongoQuery.setConditions(conditions);
                    Long count = iIsfdDatabaseMongoService.count(tableName, isfdDatabaseMongoQuery);
                    if (count > 0) {
                        throw new BaseException("业务场景: " + refVo.getSceneName() + "要素数据库类型: " + refVo.getDataBaseName() + "业务系统: " + refVo.getSystemName() + "模型名称: " + refVo.getModelName() + ",已经导入数据，不能删除！");
                    }
                }
            }
        }
    }

    @Override
    @Transactional
    public void deleteByKey(Long sceneId, Long databaseTypeId, Long systemId, Long parentModelId) {
        LambdaQueryWrapper<IsfdBusinessDatabaseRef> lqw = new LambdaQueryWrapper<IsfdBusinessDatabaseRef>()
            .eq(sceneId != null, IsfdBusinessDatabaseRef::getSceneId, sceneId)
            .eq(databaseTypeId != null, IsfdBusinessDatabaseRef::getDatabaseTypeId, databaseTypeId)
            .eq(systemId != null, IsfdBusinessDatabaseRef::getSystemId, systemId)
            .eq(parentModelId != null, IsfdBusinessDatabaseRef::getParentModelId, parentModelId);
        // 需要删除系统地图
        iIsfdSceneMapService.checkByConditionsForDelete(sceneId, databaseTypeId, systemId, parentModelId);
        baseMapper.delete(lqw);
    }

}
